home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Communication / NewsBase / Source / INewsgroupInfoD.m < prev    next >
Text File  |  1993-01-12  |  9KB  |  342 lines

  1.  
  2. /* Generated by Interface Builder */
  3.  
  4. #import "INewsgroupInfoD.h"
  5. #import "IZIntPair.h"
  6. #import "data_types.h"
  7. #import "errdebug.h"
  8. #import <objc/List.h>
  9. #import <appkit/Panel.h>
  10. #import <stdio.h>
  11. #import <string.h>
  12. #import <objc/zone.h>
  13.  
  14. #import "Localization.h"
  15.  
  16. #define LoStr(key)      doLocalString(NULL,key,NULL)
  17.  
  18.  
  19. @implementation INewsgroupInfoD
  20.  
  21. - initWithKey:(const char *)dataKey
  22. {
  23.     iPairList = [[List allocFromZone:[self zone]] init];
  24.     [super initWithKey:dataKey];
  25.     return self;
  26. }
  27.  
  28. - (BOOL)checkArticleIsRead:(int)kartnum
  29. {
  30.     int        ti;
  31.     IZIntPair    *intPair;
  32.     
  33.     [self _readArticleNumSet];        /* set art_num_set to ipair_a_num[] */
  34.                     /* if it's already read : return YES */
  35.                     /*         not read:      return NO */
  36.     for (ti=0; intPair=[iPairList objectAt:ti]; ++ti) {
  37.     if (([intPair first] <= kartnum) && (kartnum <= [intPair last]))
  38.         return YES;
  39.     }
  40.     return NO;
  41. }
  42.  
  43. - (void)markReadArticle:(int)kartnum;
  44. {
  45.     int        i;
  46.     IZIntPair    *intPair, *lastIntPair, *rightPair, *newPair;
  47.     int        maxIndex;
  48.  
  49.     [self _readArticleNumSet];
  50.     if ([self checkArticleIsRead:kartnum]) /*set art_num_set to ipair_a_num */ 
  51.     return;                   /*if already marked, return */
  52.  
  53.     /* handle last object */
  54.     lastIntPair = [iPairList lastObject];
  55.     if (([iPairList count]==0) || ([lastIntPair last] < kartnum)){
  56.     if (([lastIntPair last] +1) == kartnum ) {
  57.         /* xxx-xxx type */
  58.         [lastIntPair setLast:kartnum];
  59.     } else {
  60.         /* xxx-xxx,xxx type */
  61.         newPair = [[IZIntPair allocFromZone:[self zone]] init];
  62.         [newPair setFirst:kartnum last:kartnum];
  63.         [iPairList addObject:newPair];
  64.     }
  65.         [self _writeArticleNumSet];
  66.         return;
  67.     }
  68.  
  69.     maxIndex = [iPairList count] - 1;
  70.     for (i=(maxIndex-1); i>=0; i--) {
  71.     intPair = [iPairList objectAt:i];
  72.     rightPair = [iPairList objectAt:(i+1)];
  73.     if (([intPair last] < kartnum) && (kartnum < [rightPair first])) {
  74.         if (([intPair last]+1 == kartnum) 
  75.                && ( kartnum+1 == [rightPair first])) {
  76.         /* 0-219,210,211-220 -> 0-220 type */
  77.         [intPair setLast:[rightPair last]];
  78.         /* remove rightPair */
  79.         [iPairList removeObjectAt:(i+1)];
  80.         [rightPair free];
  81.         } else if (([intPair last]+1) == kartnum) {
  82.         /* 0-120,121,210-220 -> 0-121,210-220 type */
  83.         [intPair setLast:kartnum];
  84.         } else if ((kartnum+1) == [rightPair first]) {
  85.         /* 0-120,219,210-220 -> 0-120,219-220 type */
  86.         [rightPair setFirst:kartnum];
  87.         } else {
  88.         /* 0-120,150,210-220 type */
  89.         /* insert object */
  90.         newPair = [[IZIntPair allocFromZone:[self zone]] init];
  91.         [iPairList insertObject:newPair at:(i+1)];
  92.         [newPair setFirst:kartnum last:kartnum];
  93.         }
  94.     }
  95.     }
  96.     /* put read-article data to groupInfo */
  97.     [self _writeArticleNumSet];
  98.     
  99.     return;
  100. }
  101.  
  102. - (BOOL)isAllArticleMarked
  103. {
  104.     int        first, last;
  105.     int        i;
  106.     
  107.     first = (int)[self infoForKey:FIRST];
  108.     last  = (int)[self infoForKey:LAST];
  109.     
  110.     for (i=first; i<=last; ++i) {
  111.     if ([self checkArticleIsRead:i]==NO) {
  112.         return NO;
  113.     }
  114.     }
  115.     return YES;
  116. }
  117.  
  118. - (int)countArticleUnMarked
  119. {
  120.     int        first, last;
  121.     int        i;
  122.     int        art_count;
  123.     
  124.     first = (int)[self infoForKey:FIRST];
  125.     last  = (int)[self infoForKey:LAST];
  126.     
  127.     art_count = 0;
  128.     for (i=first; i<=last; ++i) {
  129.     if ([self checkArticleIsRead:i]==NO) {
  130.         ++art_count;
  131.     }
  132.     }
  133.     return art_count;
  134. }
  135.  
  136. - (void)unmarkReadArticle:(int)kartnum
  137. {
  138.     int        i;
  139.     IZIntPair    *intPair, *newPair;
  140.  
  141.     [self _readArticleNumSet];         /*set art_num_set to ipair_a_num */ 
  142.     if (!([self checkArticleIsRead:kartnum]))
  143.     return;                   /*if not marked, return */
  144.     
  145.     for (i=0; intPair=[iPairList objectAt:i]; i++) {
  146.     /* xxx */
  147.     if (kartnum==[intPair first] && kartnum==[intPair last]) {
  148.         /* remove xxx */
  149.         if ([intPair first] == kartnum) {
  150.         /* copy, 123-150,176,180-210 -> 123-150,180-210 */
  151.         [iPairList removeObjectAt:i];
  152.         [intPair free];
  153.         break;
  154.         }
  155.     /* xxx-xxx */
  156.     } else if ([intPair first] == kartnum) {
  157.         /* 123-150 -> 124-150 */
  158.         [intPair setFirst:([intPair first]+1)];
  159.         break;
  160.     } else if ([intPair last] == kartnum) {
  161.         /* 123-150 -> 123-149 */
  162.         [intPair setLast:([intPair last]-1)];
  163.         break;
  164.     } else if (([intPair first] < kartnum) && (kartnum < [intPair last])) {
  165.         /* 123-150 -> 123-135,137-150 */
  166.         /* copy */
  167.         newPair = [[IZIntPair allocFromZone:[self zone]] init];
  168.         [iPairList insertObject:newPair at:(i+1)];
  169.         [newPair setFirst:(kartnum+1) last:[intPair last]];
  170.         [intPair setLast:(kartnum-1)];
  171.         break;
  172.     }
  173.     }
  174.     /* put read-article data to groupInfo */
  175.     [self _writeArticleNumSet];
  176.     return;
  177. }
  178.  
  179. - (void)markAllArticle
  180. {
  181.     IZIntPair    *intPair;
  182.     
  183.     [iPairList freeObjects];
  184.     intPair = [[IZIntPair allocFromZone:[self zone]] init];
  185.     [iPairList addObject:intPair];
  186.     [intPair setFirst:0 last:(int)[self infoForKey:LAST]];
  187.     [self _writeArticleNumSet];
  188.     return;
  189. }
  190.  
  191. - (void)_readArticleNumSet
  192. {
  193.     char    *art_num_set, ch;
  194.     int        first, last;
  195.     int        num_read;
  196.     IZIntPair    *intPair;
  197.     
  198.     if ([iPairList count] > 0) {
  199.         return;
  200.     }
  201.     art_num_set = (char *)[self infoForKey:ART_NUM_SET];
  202.     
  203.                 /* store data to instance val. */
  204.     ch=' ';
  205.     while ((num_read = sscanf(art_num_set,"%d-%d", &first, &last))
  206.                 && ch !='\0') {
  207.     intPair = [[IZIntPair allocFromZone:[self zone]] init];
  208.     [iPairList addObject:intPair];
  209.  
  210.     if (num_read == 2) {            /* xxx-xxx type */
  211.         [intPair setFirst:first last:last];        
  212.     } else {                /* xxx type */
  213.         [intPair setFirst:first last:first];
  214.     }                     /* descripter is '.' or ' ' */
  215.                         /* and go to next descripter */
  216.     /* skip the pointer(art_num_set) to the head of next set */
  217. //    while(!((ch = *(art_num_set++)) == ','  || ch == ' ' || ch =='\0'))
  218.     while(!((ch = *(art_num_set++)) == ','  || ch =='\0'))
  219.             ;
  220.     }
  221.     if ([iPairList count] == 0) {
  222.     intPair = [[IZIntPair allocFromZone:[self zone]] init];
  223.     [iPairList addObject:intPair];
  224.     [intPair setFirst:(int)0 last:(int)0];
  225.     }
  226.     return;
  227. }
  228.  
  229. - (void)_writeArticleNumSet
  230. {
  231. #define        LINE_MAX_LEN        4088
  232.  
  233.     int        i;
  234.     char    line_buf[LINE_MAX_LEN], *line_buf_ptr;
  235.     IZIntPair    *intPair;
  236.                         /* print art num. set */    
  237.     line_buf[0] = '\0';
  238.     line_buf_ptr = line_buf;
  239.  
  240.     for (i=0; intPair=[iPairList objectAt:i]; ++i) {
  241.     if (strlen(line_buf) > (LINE_MAX_LEN - 24)) {
  242.         /* 4 byte integer needs 10 chars, so 20. and '-'','' ''\0' */
  243.         NXRunAlertPanel(LoStr("NewsBase"),
  244.         LoStr("newsrc file: length of line over flow"),
  245.         LoStr("OK"),NULL,NULL);
  246.         return;
  247.     }
  248.     /* move pointer to string's end */
  249.         line_buf_ptr = strchr(line_buf, '\0');
  250.     if ([intPair first] < [intPair last]) {
  251.                             /* ..., xxx-xxx */
  252.         sprintf(line_buf_ptr, "%d-%d",
  253.                 (int)[intPair first], (int)[intPair last]);
  254.     } else {
  255.                             /* ..., xxx */
  256.         sprintf(line_buf_ptr, "%d", (int)[intPair first]);
  257.     }
  258.                     /* move pointer to string's end */
  259.     line_buf_ptr = strchr(line_buf, '\0');
  260.     if (i != ([iPairList count]-1)) {
  261.                                 /* add ',' */
  262.         sprintf (line_buf_ptr, ",");
  263.     }
  264.     }
  265.     DBG(1,fprintf (stderr," art_num_set = %s\n", line_buf));
  266.     [self addInfoString:line_buf key:ART_NUM_SET];
  267. }
  268.  
  269. - (int)firstArticleForAmount:(int)artWillGetNum
  270. {
  271.     int        amount;
  272.     int        last;
  273.     int        i;
  274.     
  275.     if (artWillGetNum==0) {
  276.     return 0;
  277.     }
  278.     last = (int)[self infoForKey:LAST];
  279.     amount = [self countArticleUnMarked];
  280.     i = last + 1;
  281.     
  282.     while ((artWillGetNum > 0) && (amount > 0) && (--i > 0)) {
  283.     if ([self checkArticleIsRead:i]==NO) {
  284.         /* article is unmarked one */
  285.         --artWillGetNum;
  286.         --amount;
  287.     }
  288.     }
  289.     return i;
  290. }
  291.  
  292. - addInfoInt:(int)theValue key:(char *)theKey;
  293. {
  294.     unsigned int    i, ti;
  295.     int        first, last, ex_last;
  296.     IZIntPair    *intPair;
  297.  
  298.     if (strcmp(theKey,FIRST) == 0) {
  299.     /* key is FIRST, try to clean up ART_NUM_SET */
  300.     if ([self infoForKey:ART_NUM_SET] != nil) {
  301.         /* this groupinfo has ART_NUM_SET, iPairList is set */
  302.         for (i=[iPairList count]-1;
  303.             ((intPair=[iPairList objectAt:i])!=nil && i!=0); i--) {
  304.         first = [intPair first];
  305.         last = [intPair last];
  306.         ex_last = theValue - 1;
  307.         /* if there is "1, ... xxx-yyy .... theValue", */
  308.         /* remove article # set under theValue(i.e. xxx-yyy) */
  309.         /* i.e. remove "1-ex_last" */
  310.         
  311.         if (ex_last < (first-1)) {
  312.             /* theValue ... xxx-yyy */
  313.             continue;
  314.         }
  315.  
  316.         if ((first-1) <= ex_last && ex_last <= last) {
  317.             /* theValue is 124, so 0-123 is already read */
  318.             /*      0, ..., 123-130 -> 0-130, ... */
  319.             /* or,  0, ...., 120-130 -> 0-130 */
  320.             /* or,  0, ...., 120-123 -> 0-123 */
  321.             for (ti=i; ti>=1; --ti) {
  322.             [iPairList removeObjectAt:ti];
  323.             }
  324.             [[iPairList objectAt:0] setFirst:0 last:last];
  325.             break;
  326.         } else if (last < ex_last) {
  327.             /*      0, ...., xxx-120, 130-135 -> 0-123, 130-135,...*/
  328.             for (ti=i; ti>=1; --ti) {
  329.             [iPairList removeObjectAt:ti];
  330.             }
  331.             [[iPairList objectAt:0] setFirst:0 last:ex_last];
  332.             break;
  333.         } 
  334.         }
  335.     } 
  336.     }
  337.  
  338.     return [super addInfoInt:theValue key:theKey];
  339. }
  340.  
  341. @end
  342.